#include "app_buffer.h"
#include "log/log.h"
#include <stdlib.h>
#include <string.h>

Buffer *app_buffer_init(int size)
{
    // 1.判断参数合法性
    if (size <= 0)
    {
        log_error("init参数不合法:size必须大于0");

        return NULL; // 指针一般返回NULL
    }

    // 2.为buffer动态分配内存
    Buffer *buffer = (Buffer *)malloc(sizeof(buffer));
    if (buffer == NULL)
    {
        log_error("buffer内存分配失败");
        return NULL;
    }

    // 3.为*ptr动态分配内存
    buffer->ptr = malloc(size);
    if (buffer->ptr == NULL)
    {
        log_error("buffer->ptr内存分配失败");
        free(buffer); // 内部分配失败，释放外部分配的内存
        return NULL;
    }

    // 4.初始化buffer的其他属性
    buffer->total_size = size;
    buffer->offset = 0;
    buffer->len = 0;
}

void app_buffer_free(Buffer *buffer)
{
    // 1.判断参数合法性
    if (buffer == NULL)
    {
        log_error("free参数不合法");
        return;
    }

    // 先释放内 再释放外
    if (buffer->ptr != NULL)
    {
        free(buffer->ptr);
    }
    free(buffer);
}

int app_buffer_write(Buffer *buffer, char *data, int len)
{
    // 1.判断参数合法性
    if (buffer == NULL || data == NULL || len <= 0)
    {
        log_error("write参数不合法");
        return -1;
    }

    // 2.如果buffer剩余足够空间不足 返回错误
    if (buffer->total_size - buffer->len < len)
    {
        log_error("buffer剩余空间不足");
        return -1;
    }

    // 说明剩余空间足够
    // 1.计算写的起始位置:偏移量+已有长度
    int write_start = buffer->offset + buffer->len;
    // 2.如果write_start大于总长度 -> 修正起始位置  eg:16>12,修正为16-12=4
    if (write_start >= buffer->total_size)
    {
        write_start = write_start - buffer->total_size;
    }
    // 3.写数据：分一段写完 还是多段写完
    if (buffer->total_size - write_start >= len) // 一段写完
    {
        memcpy(buffer->ptr + write_start, data, len); // 参数：目标，源，长度
    }
    else // 两段写
    {
        // 计算第一段的长度
        int len1 = buffer->total_size - write_start;
        memcpy(buffer->ptr + write_start, data, len1);

        // 计算第二段的长度
        int len2 = len - len1;
        memcpy(buffer->ptr, data + len1, len2);
    }

    // 4.更新buffer的属性
    // 更新offset(写不影响offset)和len
    buffer->len += len;

    log_debug("写成功,buffer->offset:%d,buffer->len:%d,prt=%s,len:%d", buffer->offset, buffer->len, buffer->ptr, len);

    return 0; // 写成功返回0
}

int app_buffer_read(Buffer *buffer, char *data, int len)
{
    // 1.判断参数合法性
    if (buffer == NULL || data == NULL || len <= 0)
    {
        log_error("read参数不合法");
        return -1;
    }

    // 2.如果buffer中数据不足 返回错误
    if (buffer->len < len)
    {
        log_error("buffer中数据不足");
        return -1;
    }

    // 3.如果buffer中数据足够 -> 能读
    // 读数据：分一段读完 还是两段读
    if (buffer->total_size - buffer->offset >= len) // 一段读完
    {
        memcpy(data, buffer->offset + buffer->ptr, len);
        // 更新offset
        buffer->offset += len;
    }
    else // 两段读
    {
        // 计算第一段的长度
        int len1 = buffer->total_size - buffer->offset;
        memcpy(data, buffer->ptr + buffer->offset, len1);
        // 计算第二段的长度
        int len2 = len - len1;
        memcpy(data + len1, buffer->ptr, len2);

        // 更新offset
        buffer->offset = len2;
        //buffer->offset = len - len1;
    }

    // 更新offset（在读之后更新）和len
    buffer->len -= len;

    log_debug("读成功,buffer->offset:%d,buffer->len:%d,prt=%s,len:%d", buffer->offset, buffer->len, buffer->ptr, len);

    return 0; // 读成功返回0
}